home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume25 / fsp / part03 < prev    next >
Encoding:
Internet Message Format  |  1991-12-13  |  38.1 KB

  1. Subject: v25i026: A real-time, multithreaded Internet archive server, Part03/03
  2. Newsgroups: comp.sources.unix
  3. Approved: vixie@pa.dec.com
  4.  
  5. Submitted-By: wen-king@vlsi.cs.caltech.edu
  6. Posting-Number: Volume 25, Issue 26
  7. Archive-Name: fsp/part03
  8.  
  9. #! /bin/sh
  10. # This is a shell archive.  Remove anything before this line, then unpack
  11. # it by saving it into a file and typing "sh file".  To overwrite existing
  12. # files, type "sh file -c".  You can also feed this as standard input via
  13. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  14. # will see the following message at the end:
  15. #        "End of archive 3 (of 3)."
  16. # Contents:  bsd_src/ls.c bsd_src/random.c server_file.c
  17. # Wrapped by vixie@cognition.pa.dec.com on Fri Dec 13 17:53:12 1991
  18. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  19. if test -f 'bsd_src/ls.c' -a "${1}" != "-c" ; then 
  20.   echo shar: Will not clobber existing file \"'bsd_src/ls.c'\"
  21. else
  22. echo shar: Extracting \"'bsd_src/ls.c'\" \(10950 characters\)
  23. sed "s/^X//" >'bsd_src/ls.c' <<'END_OF_FILE'
  24. X/*
  25. X * Copyright (c) 1989 The Regents of the University of California.
  26. X * All rights reserved.
  27. X *
  28. X * This code is derived from software contributed to Berkeley by
  29. X * Michael Fischbein.
  30. X *
  31. X * Redistribution and use in source and binary forms are permitted
  32. X * provided that: (1) source distributions retain this entire copyright
  33. X * notice and comment, and (2) distributions including binaries display
  34. X * the following acknowledgement:  ``This product includes software
  35. X * developed by the University of California, Berkeley and its contributors''
  36. X * in the documentation or other materials provided with the distribution
  37. X * and in all advertising materials mentioning features or use of this
  38. X * software. Neither the name of the University nor the names of its
  39. X * contributors may be used to endorse or promote products derived
  40. X * from this software without specific prior written permission.
  41. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  42. X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  43. X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  44. X */
  45. X
  46. X#ifndef lint
  47. char copyright[] =
  48. X"@(#) Copyright (c) 1989 The Regents of the University of California.\n\
  49. X All rights reserved.\n";
  50. X#endif /* not lint */
  51. X
  52. X#ifndef lint
  53. static char sccsid[] = "@(#)ls.c    5.42 (Berkeley) 5/17/90";
  54. X#endif /* not lint */
  55. X
  56. X#include "../client_def.h"
  57. X#include <sys/ioctl.h>
  58. X#include <string.h>
  59. X#include "ls.h"
  60. X#include "tweak.h"
  61. X
  62. int (*sortfcn)(), (*printfcn)();
  63. char *emalloc();
  64. X
  65. int termwidth = 80;        /* default terminal width */
  66. X
  67. X/* flags */
  68. int f_accesstime;        /* use time of last access */
  69. int f_column;            /* columnated format */
  70. int f_group;            /* show group ownership of a file */
  71. int f_ignorelink;        /* indirect through symbolic link operands */
  72. int f_inode;            /* print inode */
  73. int f_kblocks;            /* print size in kilobytes */
  74. int f_listalldot;        /* list . and .. as well */
  75. int f_listdir;            /* list actual directory, not contents */
  76. int f_listdot;            /* list files beginning with . */
  77. int f_longform;            /* long listing format */
  78. int f_needstat;            /* if need to stat files */
  79. int f_newline;            /* if precede with newline */
  80. int f_nonprint;            /* show unprintables as ? */
  81. int f_nosort;            /* don't sort output */
  82. int f_recursive;        /* ls subdirectories also */
  83. int f_reversesort;        /* reverse whatever sort is used */
  84. int f_singlecol;        /* use single column output */
  85. int f_size;            /* list size in short listing */
  86. int f_statustime;        /* use time of last mode change */
  87. int f_dirname;            /* if precede with directory name */
  88. int f_timesort;            /* sort by time vice name */
  89. int f_total;            /* if precede with "total" line */
  90. int f_type;            /* add type character for non-regular files */
  91. X
  92. fls_main(argc, argv)
  93. X    int argc;
  94. X    char **argv;
  95. X{
  96. X    extern int optind;
  97. X    int ch;
  98. X    char *p, *getenv();
  99. X    int acccmp(), modcmp(), namecmp(), prcopy(), printcol();
  100. X    int printlong(), printscol(), revacccmp(), revmodcmp(), revnamecmp();
  101. X    int revstatcmp(), statcmp();
  102. X
  103. X    /* terminal defaults to -Cq, non-terminal defaults to -1 */
  104. X    if (isatty(1)) {
  105. X        f_nonprint = 1;
  106. X        termwidth  = 80;
  107. X#ifdef TIOCGWINSZ
  108. X        {   struct winsize win;
  109. X            if (ioctl(1, TIOCGWINSZ, &win) == -1 || !win.ws_col) {
  110. X                if (p = getenv("COLUMNS"))
  111. X                    termwidth = atoi(p);
  112. X            }
  113. X            else
  114. X                termwidth = win.ws_col;
  115. X        }
  116. X#endif
  117. X        f_column = 1;
  118. X    } else
  119. X        f_singlecol = 1;
  120. X
  121. X    /* root is -A automatically */
  122. X    if (!getuid())
  123. X        f_listdot = 1;
  124. X
  125. X    while ((ch = getopt(argc, argv, "1ACFLRacdfgiklqrstu")) != EOF) {
  126. X        switch (ch) {
  127. X        /*
  128. X         * -1, -C and -l all override each other
  129. X         * so shell aliasing works right
  130. X         */
  131. X        case '1':
  132. X            f_singlecol = 1;
  133. X            f_column = f_longform = 0;
  134. X            break;
  135. X        case 'C':
  136. X            f_column = 1;
  137. X            f_longform = f_singlecol = 0;
  138. X            break;
  139. X        case 'l':
  140. X            f_longform = 1;
  141. X            f_column = f_singlecol = 0;
  142. X            break;
  143. X        /* -c and -u override each other */
  144. X        case 'c':
  145. X            f_statustime = 1;
  146. X            f_accesstime = 0;
  147. X            break;
  148. X        case 'u':
  149. X            f_accesstime = 1;
  150. X            f_statustime = 0;
  151. X            break;
  152. X        case 'F':
  153. X            f_type = 1;
  154. X            break;
  155. X        case 'L':
  156. X            f_ignorelink = 1;
  157. X            break;
  158. X        case 'R':
  159. X            f_recursive = 1;
  160. X            break;
  161. X        case 'a':
  162. X            f_listalldot = 1;
  163. X            /* FALLTHROUGH */
  164. X        case 'A':
  165. X            f_listdot = 1;
  166. X            break;
  167. X        case 'd':
  168. X            f_listdir = 1;
  169. X            break;
  170. X        case 'f':
  171. X            f_nosort = 1;
  172. X            break;
  173. X        case 'g':
  174. X            f_group = 1;
  175. X            break;
  176. X        case 'i':
  177. X            f_inode = 1;
  178. X            break;
  179. X        case 'k':
  180. X            f_kblocks = 1;
  181. X            break;
  182. X        case 'q':
  183. X            f_nonprint = 1;
  184. X            break;
  185. X        case 'r':
  186. X            f_reversesort = 1;
  187. X            break;
  188. X        case 's':
  189. X            f_size = 1;
  190. X            break;
  191. X        case 't':
  192. X            f_timesort = 1;
  193. X            break;
  194. X        default:
  195. X        case '?':
  196. X            usage();
  197. X        }
  198. X    }
  199. X    argc -= optind;
  200. X    argv += optind;
  201. X
  202. X    /* -d turns off -R */
  203. X    if (f_listdir)
  204. X        f_recursive = 0;
  205. X
  206. X    /* if need to stat files */
  207. X    f_needstat = f_longform || f_recursive || f_timesort ||
  208. X        f_size || f_type;
  209. X
  210. X    /* select a sort function */
  211. X    if (f_reversesort) {
  212. X        if (!f_timesort)
  213. X            sortfcn = revnamecmp;
  214. X        else if (f_accesstime)
  215. X            sortfcn = revacccmp;
  216. X        else if (f_statustime)
  217. X            sortfcn = revstatcmp;
  218. X        else /* use modification time */
  219. X            sortfcn = revmodcmp;
  220. X    } else {
  221. X        if (!f_timesort)
  222. X            sortfcn = namecmp;
  223. X        else if (f_accesstime)
  224. X            sortfcn = acccmp;
  225. X        else if (f_statustime)
  226. X            sortfcn = statcmp;
  227. X        else /* use modification time */
  228. X            sortfcn = modcmp;
  229. X    }
  230. X
  231. X    /* select a print function */
  232. X    if (f_singlecol)
  233. X        printfcn = printscol;
  234. X    else if (f_longform)
  235. X        printfcn = printlong;
  236. X    else
  237. X        printfcn = printcol;
  238. X
  239. X    if (!argc) {
  240. X        argc = 1;
  241. X        argv[0] = ".";
  242. X        argv[1] = NULL;
  243. X    }
  244. X    doargs(argc, argv);
  245. X}
  246. X
  247. static char path[2*1024 + 1];
  248. static char *endofpath = path;
  249. X
  250. doargs(argc, argv)
  251. X    int argc;
  252. X    char **argv;
  253. X{
  254. X    register LS *dstatp, *rstatp;
  255. X    register int cnt, dircnt, dirmax, maxlen, regcnt, regmax;
  256. X    LS *dstats, *rstats;
  257. X    struct stat sb;
  258. X    char top[2*1024 + 1], **av, *av2[2];
  259. X    unsigned long blocks;
  260. X    extern char **glob();
  261. X
  262. X    /*
  263. X     * walk through the operands, building separate arrays of LS
  264. X     * structures for directory and non-directory files.
  265. X     */
  266. X    dstats = rstats = NULL;
  267. X    dirmax = regmax = 0;
  268. X
  269. X    for (dircnt = regcnt = 0; *argv; ++argv)
  270. X    {
  271. X        if(!(av = glob(*argv))) { av = av2; av2[0] = *argv; av2[1] = 0; }
  272. X
  273. X        for( ; *av; av++)
  274. X        {
  275. X        if (util_stat(*av, &sb)) {
  276. X            perror(*av);
  277. X            if (errno == ENOENT)
  278. X                continue;
  279. X            ls_bad(1);
  280. X        }
  281. X        if ((S_IFDIR & sb.st_mode) && !f_listdir) {
  282. X            if(dirmax == dircnt)
  283. X            {
  284. X                dirmax += 10;
  285. X                if (!dstats)
  286. X                {
  287. X                dstatp = dstats = (LS *)emalloc(dirmax *
  288. X                                (sizeof(LS)));
  289. X                } else 
  290. X                {
  291. X                dstats = (LS *)realloc(dstats,
  292. X                            dirmax * (sizeof(LS)));
  293. X                dstatp = dstats + dircnt;
  294. X                }
  295. X            }
  296. X            dstatp->name = *av;
  297. X            dstatp->lstat = sb;
  298. X            ++dstatp;
  299. X            ++dircnt;
  300. X        }
  301. X        else {
  302. X            if(regmax == regcnt)
  303. X            {
  304. X                regmax += 10;
  305. X
  306. X                if (!rstats)
  307. X                {
  308. X                blocks = 0;
  309. X                maxlen = -1;
  310. X                rstatp = rstats = (LS *)emalloc(regmax *
  311. X                            (sizeof(LS)));
  312. X                } else
  313. X                {
  314. X                rstats = (LS *)realloc(rstats,
  315. X                            regmax * (sizeof(LS)));
  316. X                rstatp = rstats + regcnt;
  317. X                }
  318. X            }
  319. X            rstatp->name = *av;
  320. X            rstatp->lstat = sb;
  321. X
  322. X            /* save name length for -C format */
  323. X            rstatp->len = strlen(*av);
  324. X
  325. X            if (f_nonprint)
  326. X                prcopy(*av, *av, rstatp->len);
  327. X
  328. X            /* calculate number of blocks if -l/-s formats */
  329. X            if (f_longform || f_size)
  330. X                blocks += (sb.st_size + 1023)/1024;
  331. X
  332. X            /* save max length if -C format */
  333. X            if (f_column && maxlen < rstatp->len)
  334. X                maxlen = rstatp->len;
  335. X
  336. X            ++rstatp;
  337. X            ++regcnt;
  338. X        }
  339. X        }
  340. X    }
  341. X    /* display regular files */
  342. X    if (regcnt) {
  343. X        rstats[0].lstat.st_btotal = blocks;
  344. X        rstats[0].lstat.st_maxlen = maxlen;
  345. X        displaydir(rstats, regcnt);
  346. X        f_newline = f_dirname = 1;
  347. X    }
  348. X    /* display directories */
  349. X    if (dircnt) {
  350. X        register char *p;
  351. X
  352. X        f_total = 1;
  353. X        if (dircnt > 1) {
  354. X            (void)util_getwd(top);
  355. X            qsort((char *)dstats, dircnt, sizeof(LS), sortfcn);
  356. X            f_dirname = 1;
  357. X        }
  358. X        for (cnt = 0; cnt < dircnt; ++dstats) {
  359. X            for (endofpath = path, p = dstats->name;
  360. X                *endofpath = *p++; ++endofpath);
  361. X            subdir(dstats);
  362. X            f_newline = 1;
  363. X            if (++cnt < dircnt && util_cd(top)) {
  364. X                perror(top);
  365. X                ls_bad(1);
  366. X            }
  367. X        }
  368. X    }
  369. X}
  370. X
  371. displaydir(stats, num)
  372. X    LS *stats;
  373. X    register int num;
  374. X{
  375. X    register char *p, *savedpath;
  376. X    LS *lp;
  377. X
  378. X    if (num > 1 && !f_nosort) {
  379. X        unsigned long save1, save2;
  380. X
  381. X        save1 = stats[0].lstat.st_btotal;
  382. X        save2 = stats[0].lstat.st_maxlen;
  383. X        qsort((char *)stats, num, sizeof(LS), sortfcn);
  384. X        stats[0].lstat.st_btotal = save1;
  385. X        stats[0].lstat.st_maxlen = save2;
  386. X    }
  387. X
  388. X    printfcn(stats, num);
  389. X
  390. X    if (f_recursive) {
  391. X        savedpath = endofpath;
  392. X        for (lp = stats; num--; ++lp) {
  393. X            if (!(S_IFDIR & lp->lstat.st_mode))
  394. X                continue;
  395. X            p = lp->name;
  396. X            if (p[0] == '.' && (!p[1] || p[1] == '.' && !p[2]))
  397. X                continue;
  398. X            if (endofpath != path && endofpath[-1] != '/')
  399. X                *endofpath++ = '/';
  400. X            for (; *endofpath = *p++; ++endofpath);
  401. X            f_newline = f_dirname = f_total = 1;
  402. X            subdir(lp);
  403. X            *(endofpath = savedpath) = '\0';
  404. X        }
  405. X    }
  406. X}
  407. X
  408. subdir(lp)
  409. X    LS *lp;
  410. X{
  411. X    LS *stats;
  412. X    int num;
  413. X
  414. X    if (f_newline)
  415. X        (void)putchar('\n');
  416. X    if (f_dirname)
  417. X        (void)printf("%s:\n", path);
  418. X
  419. X    if (util_cd(lp->name)) {
  420. X        perror(lp->name);
  421. X        return;
  422. X    }
  423. X    if (num = tabdir(lp, &stats)) {
  424. X        displaydir(stats, num);
  425. X        (void)free((char *)stats);
  426. X    }
  427. X    if (util_cd("..")) {
  428. X        perror("..");
  429. X        ls_bad(1);
  430. X    }
  431. X}
  432. X
  433. tabdir(lp, s_stats)
  434. X    LS *lp, **s_stats;
  435. X{
  436. X    register RDIR *dirp;
  437. X    register int cnt, maxentry, maxlen;
  438. X    register char *p;
  439. X    struct rdirent *dp;
  440. X    unsigned long blocks;
  441. X    LS *stats;
  442. X
  443. X    if (!(dirp = util_opendir("."))) {
  444. X        perror(lp->name);
  445. X        return(0);
  446. X    }
  447. X    blocks = maxentry = maxlen = 0;
  448. X    stats = NULL;
  449. X    for (cnt = 0; dp = util_readdir(dirp);) {
  450. X        /* this does -A and -a */
  451. X        p = dp->d_name;
  452. X        if (p[0] == '.') {
  453. X            if (!f_listdot)
  454. X                continue;
  455. X            if (!f_listalldot && (!p[1] || p[1] == '.' && !p[2]))
  456. X                continue;
  457. X        }
  458. X        if (cnt == maxentry) {
  459. X#define    DEFNUM    256
  460. X            maxentry += DEFNUM;
  461. X            if(stats)
  462. X            {
  463. X              if (!(*s_stats = stats = (LS *)realloc((char *)stats,
  464. X                (unsigned int)maxentry * sizeof(LS))))
  465. X                nomem();
  466. X            } else
  467. X            {
  468. X              if (!(*s_stats = stats = (LS *)malloc(
  469. X                (unsigned int)maxentry * sizeof(LS))))
  470. X                nomem();
  471. X            }
  472. X        }
  473. X        if (f_needstat && util_stat(dp->d_name, &stats[cnt].lstat)) {
  474. X            /*
  475. X             * don't exit -- this could be an NFS mount that has
  476. X             * gone away.  Flush stdout so the messages line up.
  477. X             */
  478. X            (void)fflush(stdout);
  479. X            perror(dp->d_name);
  480. X            continue;
  481. X        }
  482. X        stats[cnt].name = dp->d_name;
  483. X
  484. X        /*
  485. X         * get the inode from the directory, so the -f flag
  486. X         * works right.
  487. X         */
  488. X        stats[cnt].lstat.st_ino = dp->d_ino;
  489. X
  490. X        /* save name length for -C format */
  491. X        stats[cnt].len = dp->d_namlen;
  492. X
  493. X        /* calculate number of blocks if -l/-s formats */
  494. X        if (f_longform || f_size)
  495. X            blocks += (stats[cnt].lstat.st_size + 1023)/1024;
  496. X
  497. X        /* save max length if -C format */
  498. X        if (f_column && maxlen < (int)dp->d_namlen)
  499. X            maxlen = dp->d_namlen;
  500. X        ++cnt;
  501. X    }
  502. X    (void)util_closedir(dirp);
  503. X
  504. X    if (cnt) {
  505. X        stats[0].lstat.st_btotal = blocks;
  506. X        stats[0].lstat.st_maxlen = maxlen;
  507. X    } else if (stats) {
  508. X        (void)free((char *)stats);
  509. X    }
  510. X    return(cnt);
  511. X}
  512. END_OF_FILE
  513. if test 10950 -ne `wc -c <'bsd_src/ls.c'`; then
  514.     echo shar: \"'bsd_src/ls.c'\" unpacked with wrong size!
  515. fi
  516. # end of 'bsd_src/ls.c'
  517. fi
  518. if test -f 'bsd_src/random.c' -a "${1}" != "-c" ; then 
  519.   echo shar: Will not clobber existing file \"'bsd_src/random.c'\"
  520. else
  521. echo shar: Extracting \"'bsd_src/random.c'\" \(12955 characters\)
  522. sed "s/^X//" >'bsd_src/random.c' <<'END_OF_FILE'
  523. X/*
  524. X * Copyright (c) 1983 Regents of the University of California.
  525. X * All rights reserved.
  526. X *
  527. X * Redistribution and use in source and binary forms are permitted
  528. X * provided that: (1) source distributions retain this entire copyright
  529. X * notice and comment, and (2) distributions including binaries display
  530. X * the following acknowledgement:  ``This product includes software
  531. X * developed by the University of California, Berkeley and its contributors''
  532. X * in the documentation or other materials provided with the distribution
  533. X * and in all advertising materials mentioning features or use of this
  534. X * software. Neither the name of the University nor the names of its
  535. X * contributors may be used to endorse or promote products derived
  536. X * from this software without specific prior written permission.
  537. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  538. X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  539. X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  540. X */
  541. X
  542. X#if defined(LIBC_SCCS) && !defined(lint)
  543. static char sccsid[] = "@(#)random.c    5.7 (Berkeley) 6/1/90";
  544. X#endif /* LIBC_SCCS and not lint */
  545. X
  546. X#include <stdio.h>
  547. X
  548. X/*
  549. X * random.c:
  550. X * An improved random number generation package.  In addition to the standard
  551. X * rand()/srand() like interface, this package also has a special state info
  552. X * interface.  The initstate() routine is called with a seed, an array of
  553. X * bytes, and a count of how many bytes are being passed in; this array is then
  554. X * initialized to contain information for random number generation with that
  555. X * much state information.  Good sizes for the amount of state information are
  556. X * 32, 64, 128, and 256 bytes.  The state can be switched by calling the
  557. X * setstate() routine with the same array as was initiallized with initstate().
  558. X * By default, the package runs with 128 bytes of state information and
  559. X * generates far better random numbers than a linear congruential generator.
  560. X * If the amount of state information is less than 32 bytes, a simple linear
  561. X * congruential R.N.G. is used.
  562. X * Internally, the state information is treated as an array of longs; the
  563. X * zeroeth element of the array is the type of R.N.G. being used (small
  564. X * integer); the remainder of the array is the state information for the
  565. X * R.N.G.  Thus, 32 bytes of state information will give 7 longs worth of
  566. X * state information, which will allow a degree seven polynomial.  (Note: the 
  567. X * zeroeth word of state information also has some other information stored
  568. X * in it -- see setstate() for details).
  569. X * The random number generation technique is a linear feedback shift register
  570. X * approach, employing trinomials (since there are fewer terms to sum up that
  571. X * way).  In this approach, the least significant bit of all the numbers in
  572. X * the state table will act as a linear feedback shift register, and will have
  573. X * period 2^deg - 1 (where deg is the degree of the polynomial being used,
  574. X * assuming that the polynomial is irreducible and primitive).  The higher
  575. X * order bits will have longer periods, since their values are also influenced
  576. X * by pseudo-random carries out of the lower bits.  The total period of the
  577. X * generator is approximately deg*(2**deg - 1); thus doubling the amount of
  578. X * state information has a vast influence on the period of the generator.
  579. X * Note: the deg*(2**deg - 1) is an approximation only good for large deg,
  580. X * when the period of the shift register is the dominant factor.  With deg
  581. X * equal to seven, the period is actually much longer than the 7*(2**7 - 1)
  582. X * predicted by this formula.
  583. X */
  584. X
  585. X
  586. X
  587. X/*
  588. X * For each of the currently supported random number generators, we have a
  589. X * break value on the amount of state information (you need at least this
  590. X * many bytes of state info to support this random number generator), a degree
  591. X * for the polynomial (actually a trinomial) that the R.N.G. is based on, and
  592. X * the separation between the two lower order coefficients of the trinomial.
  593. X */
  594. X
  595. X#define        TYPE_0        0        /* linear congruential */
  596. X#define        BREAK_0        8
  597. X#define        DEG_0        0
  598. X#define        SEP_0        0
  599. X
  600. X#define        TYPE_1        1        /* x**7 + x**3 + 1 */
  601. X#define        BREAK_1        32
  602. X#define        DEG_1        7
  603. X#define        SEP_1        3
  604. X
  605. X#define        TYPE_2        2        /* x**15 + x + 1 */
  606. X#define        BREAK_2        64
  607. X#define        DEG_2        15
  608. X#define        SEP_2        1
  609. X
  610. X#define        TYPE_3        3        /* x**31 + x**3 + 1 */
  611. X#define        BREAK_3        128
  612. X#define        DEG_3        31
  613. X#define        SEP_3        3
  614. X
  615. X#define        TYPE_4        4        /* x**63 + x + 1 */
  616. X#define        BREAK_4        256
  617. X#define        DEG_4        63
  618. X#define        SEP_4        1
  619. X
  620. X
  621. X/*
  622. X * Array versions of the above information to make code run faster -- relies
  623. X * on fact that TYPE_i == i.
  624. X */
  625. X
  626. X#define        MAX_TYPES    5        /* max number of types above */
  627. X
  628. static  int        degrees[ MAX_TYPES ]    = { DEG_0, DEG_1, DEG_2,
  629. X                                DEG_3, DEG_4 };
  630. X
  631. static  int        seps[ MAX_TYPES ]    = { SEP_0, SEP_1, SEP_2,
  632. X                                SEP_3, SEP_4 };
  633. X
  634. X
  635. X
  636. X/*
  637. X * Initially, everything is set up as if from :
  638. X *        initstate( 1, &randtbl, 128 );
  639. X * Note that this initialization takes advantage of the fact that srandom()
  640. X * advances the front and rear pointers 10*rand_deg times, and hence the
  641. X * rear pointer which starts at 0 will also end up at zero; thus the zeroeth
  642. X * element of the state information, which contains info about the current
  643. X * position of the rear pointer is just
  644. X *    MAX_TYPES*(rptr - state) + TYPE_3 == TYPE_3.
  645. X */
  646. X
  647. static  long        randtbl[ DEG_3 + 1 ]    = { TYPE_3,
  648. X                0x9a319039, 0x32d9c024, 0x9b663182, 0x5da1f342, 
  649. X                0xde3b81e0, 0xdf0a6fb5, 0xf103bc02, 0x48f340fb, 
  650. X                0x7449e56b, 0xbeb1dbb0, 0xab5c5918, 0x946554fd, 
  651. X                0x8c2e680f, 0xeb3d799f, 0xb11ee0b7, 0x2d436b86, 
  652. X                0xda672e2a, 0x1588ca88, 0xe369735d, 0x904f35f7, 
  653. X                0xd7158fd6, 0x6fa6f051, 0x616e6b96, 0xac94efdc, 
  654. X                0x36413f93, 0xc622c298, 0xf5a42ab8, 0x8a88d77b, 
  655. X                    0xf5ad9d0e, 0x8999220b, 0x27fb47b9 };
  656. X
  657. X/*
  658. X * fptr and rptr are two pointers into the state info, a front and a rear
  659. X * pointer.  These two pointers are always rand_sep places aparts, as they cycle
  660. X * cyclically through the state information.  (Yes, this does mean we could get
  661. X * away with just one pointer, but the code for random() is more efficient this
  662. X * way).  The pointers are left positioned as they would be from the call
  663. X *            initstate( 1, randtbl, 128 )
  664. X * (The position of the rear pointer, rptr, is really 0 (as explained above
  665. X * in the initialization of randtbl) because the state table pointer is set
  666. X * to point to randtbl[1] (as explained below).
  667. X */
  668. X
  669. static  long        *fptr            = &randtbl[ SEP_3 + 1 ];
  670. static  long        *rptr            = &randtbl[ 1 ];
  671. X
  672. X
  673. X
  674. X/*
  675. X * The following things are the pointer to the state information table,
  676. X * the type of the current generator, the degree of the current polynomial
  677. X * being used, and the separation between the two pointers.
  678. X * Note that for efficiency of random(), we remember the first location of
  679. X * the state information, not the zeroeth.  Hence it is valid to access
  680. X * state[-1], which is used to store the type of the R.N.G.
  681. X * Also, we remember the last location, since this is more efficient than
  682. X * indexing every time to find the address of the last element to see if
  683. X * the front and rear pointers have wrapped.
  684. X */
  685. X
  686. static  long        *state            = &randtbl[ 1 ];
  687. X
  688. static  int        rand_type        = TYPE_3;
  689. static  int        rand_deg        = DEG_3;
  690. static  int        rand_sep        = SEP_3;
  691. X
  692. static  long        *end_ptr        = &randtbl[ DEG_3 + 1 ];
  693. X
  694. X
  695. X
  696. X/*
  697. X * srandom:
  698. X * Initialize the random number generator based on the given seed.  If the
  699. X * type is the trivial no-state-information type, just remember the seed.
  700. X * Otherwise, initializes state[] based on the given "seed" via a linear
  701. X * congruential generator.  Then, the pointers are set to known locations
  702. X * that are exactly rand_sep places apart.  Lastly, it cycles the state
  703. X * information a given number of times to get rid of any initial dependencies
  704. X * introduced by the L.C.R.N.G.
  705. X * Note that the initialization of randtbl[] for default usage relies on
  706. X * values produced by this routine.
  707. X */
  708. X
  709. srandom( x )
  710. X
  711. X    unsigned        x;
  712. X{
  713. X        register  int        i, j;
  714. X    long random();
  715. X
  716. X    if(  rand_type  ==  TYPE_0  )  {
  717. X        state[ 0 ] = x;
  718. X    }
  719. X    else  {
  720. X        j = 1;
  721. X        state[ 0 ] = x;
  722. X        for( i = 1; i < rand_deg; i++ )  {
  723. X        state[i] = 1103515245*state[i - 1] + 12345;
  724. X        }
  725. X        fptr = &state[ rand_sep ];
  726. X        rptr = &state[ 0 ];
  727. X        for( i = 0; i < 10*rand_deg; i++ )  random();
  728. X    }
  729. X}
  730. X
  731. X
  732. X
  733. X/*
  734. X * initstate:
  735. X * Initialize the state information in the given array of n bytes for
  736. X * future random number generation.  Based on the number of bytes we
  737. X * are given, and the break values for the different R.N.G.'s, we choose
  738. X * the best (largest) one we can and set things up for it.  srandom() is
  739. X * then called to initialize the state information.
  740. X * Note that on return from srandom(), we set state[-1] to be the type
  741. X * multiplexed with the current value of the rear pointer; this is so
  742. X * successive calls to initstate() won't lose this information and will
  743. X * be able to restart with setstate().
  744. X * Note: the first thing we do is save the current state, if any, just like
  745. X * setstate() so that it doesn't matter when initstate is called.
  746. X * Returns a pointer to the old state.
  747. X */
  748. X
  749. char  *
  750. initstate( seed, arg_state, n )
  751. X
  752. X    unsigned        seed;            /* seed for R. N. G. */
  753. X    char        *arg_state;        /* pointer to state array */
  754. X    int            n;            /* # bytes of state info */
  755. X{
  756. X    register  char        *ostate        = (char *)( &state[ -1 ] );
  757. X
  758. X    if(  rand_type  ==  TYPE_0  )  state[ -1 ] = rand_type;
  759. X    else  state[ -1 ] = MAX_TYPES*(rptr - state) + rand_type;
  760. X    if(  n  <  BREAK_1  )  {
  761. X        if(  n  <  BREAK_0  )  {
  762. X        fprintf( stderr, "initstate: not enough state (%d bytes); ignored.\n", n );
  763. X        return 0;
  764. X        }
  765. X        rand_type = TYPE_0;
  766. X        rand_deg = DEG_0;
  767. X        rand_sep = SEP_0;
  768. X    }
  769. X    else  {
  770. X        if(  n  <  BREAK_2  )  {
  771. X        rand_type = TYPE_1;
  772. X        rand_deg = DEG_1;
  773. X        rand_sep = SEP_1;
  774. X        }
  775. X        else  {
  776. X        if(  n  <  BREAK_3  )  {
  777. X            rand_type = TYPE_2;
  778. X            rand_deg = DEG_2;
  779. X            rand_sep = SEP_2;
  780. X        }
  781. X        else  {
  782. X            if(  n  <  BREAK_4  )  {
  783. X            rand_type = TYPE_3;
  784. X            rand_deg = DEG_3;
  785. X            rand_sep = SEP_3;
  786. X            }
  787. X            else  {
  788. X            rand_type = TYPE_4;
  789. X            rand_deg = DEG_4;
  790. X            rand_sep = SEP_4;
  791. X            }
  792. X        }
  793. X        }
  794. X    }
  795. X    state = &(  ( (long *)arg_state )[1]  );    /* first location */
  796. X    end_ptr = &state[ rand_deg ];    /* must set end_ptr before srandom */
  797. X    srandom( seed );
  798. X    if(  rand_type  ==  TYPE_0  )  state[ -1 ] = rand_type;
  799. X    else  state[ -1 ] = MAX_TYPES*(rptr - state) + rand_type;
  800. X    return( ostate );
  801. X}
  802. X
  803. X
  804. X
  805. X/*
  806. X * setstate:
  807. X * Restore the state from the given state array.
  808. X * Note: it is important that we also remember the locations of the pointers
  809. X * in the current state information, and restore the locations of the pointers
  810. X * from the old state information.  This is done by multiplexing the pointer
  811. X * location into the zeroeth word of the state information.
  812. X * Note that due to the order in which things are done, it is OK to call
  813. X * setstate() with the same state as the current state.
  814. X * Returns a pointer to the old state information.
  815. X */
  816. X
  817. char  *
  818. setstate( arg_state )
  819. X
  820. X    char        *arg_state;
  821. X{
  822. X    register  long        *new_state    = (long *)arg_state;
  823. X    register  int        type        = new_state[0]%MAX_TYPES;
  824. X    register  int        rear        = new_state[0]/MAX_TYPES;
  825. X    char            *ostate        = (char *)( &state[ -1 ] );
  826. X
  827. X    if(  rand_type  ==  TYPE_0  )  state[ -1 ] = rand_type;
  828. X    else  state[ -1 ] = MAX_TYPES*(rptr - state) + rand_type;
  829. X    switch(  type  )  {
  830. X        case  TYPE_0:
  831. X        case  TYPE_1:
  832. X        case  TYPE_2:
  833. X        case  TYPE_3:
  834. X        case  TYPE_4:
  835. X        rand_type = type;
  836. X        rand_deg = degrees[ type ];
  837. X        rand_sep = seps[ type ];
  838. X        break;
  839. X
  840. X        default:
  841. X        fprintf( stderr, "setstate: state info has been munged; not changed.\n" );
  842. X    }
  843. X    state = &new_state[ 1 ];
  844. X    if(  rand_type  !=  TYPE_0  )  {
  845. X        rptr = &state[ rear ];
  846. X        fptr = &state[ (rear + rand_sep)%rand_deg ];
  847. X    }
  848. X    end_ptr = &state[ rand_deg ];        /* set end_ptr too */
  849. X    return( ostate );
  850. X}
  851. X
  852. X
  853. X
  854. X/*
  855. X * random:
  856. X * If we are using the trivial TYPE_0 R.N.G., just do the old linear
  857. X * congruential bit.  Otherwise, we do our fancy trinomial stuff, which is the
  858. X * same in all ther other cases due to all the global variables that have been
  859. X * set up.  The basic operation is to add the number at the rear pointer into
  860. X * the one at the front pointer.  Then both pointers are advanced to the next
  861. X * location cyclically in the table.  The value returned is the sum generated,
  862. X * reduced to 31 bits by throwing away the "least random" low bit.
  863. X * Note: the code takes advantage of the fact that both the front and
  864. X * rear pointers can't wrap on the same call by not testing the rear
  865. X * pointer if the front one has wrapped.
  866. X * Returns a 31-bit random number.
  867. X */
  868. X
  869. long
  870. random()
  871. X{
  872. X    long        i;
  873. X    
  874. X    if(  rand_type  ==  TYPE_0  )  {
  875. X        i = state[0] = ( state[0]*1103515245 + 12345 )&0x7fffffff;
  876. X    }
  877. X    else  {
  878. X        *fptr += *rptr;
  879. X        i = (*fptr >> 1)&0x7fffffff;    /* chucking least random bit */
  880. X        if(  ++fptr  >=  end_ptr  )  {
  881. X        fptr = state;
  882. X        ++rptr;
  883. X        }
  884. X        else  {
  885. X        if(  ++rptr  >=  end_ptr  )  rptr = state;
  886. X        }
  887. X    }
  888. X    return( i );
  889. X}
  890. X
  891. END_OF_FILE
  892. if test 12955 -ne `wc -c <'bsd_src/random.c'`; then
  893.     echo shar: \"'bsd_src/random.c'\" unpacked with wrong size!
  894. fi
  895. # end of 'bsd_src/random.c'
  896. fi
  897. if test -f 'server_file.c' -a "${1}" != "-c" ; then 
  898.   echo shar: Will not clobber existing file \"'server_file.c'\"
  899. else
  900. echo shar: Extracting \"'server_file.c'\" \(11591 characters\)
  901. sed "s/^X//" >'server_file.c' <<'END_OF_FILE'
  902. X    /*********************************************************************\
  903. X    *  Copyright (c) 1991 by Wen-King Su (wen-king@vlsi.cs.caltech.edu)   *
  904. X    *                                                                     *
  905. X    *  You may copy or modify this file in any manner you wish, provided  *
  906. X    *  that this notice is always included, and that you hold the author  *
  907. X    *  harmless for any loss or damage resulting from the installation or *
  908. X    *  use of this software.                                              *
  909. X    \*********************************************************************/
  910. X
  911. X#include "server_def.h"
  912. X
  913. X/*****************************************************************************
  914. X* This file handles all file io in request to client requests.
  915. X*****************************************************************************/
  916. X
  917. X#define NBSIZE (2*sizeof(UBUF))
  918. X
  919. extern *malloc();
  920. X
  921. X#define fexist(A) (!access(A,0))
  922. X#define touch(A) close(open(A,O_CREAT,0777))
  923. X
  924. X/*****************************************************************************
  925. X* Routine to check a path string given by the client.
  926. X* Will replace null string by ".".
  927. X* In case of error, returns the error string.
  928. X*****************************************************************************/
  929. X
  930. char *check_path(path,len)
  931. X    char *path;
  932. X    int len;
  933. X{
  934. X    char *s;
  935. X    int state;
  936. X
  937. X    if(len < 1) return("Path must have non-zero lenght");
  938. X    if(len == 1 && path[0] == 0) { *path++ = '.'; *path = 0; return(NULLP); }
  939. X    if(path[len-1]) return("Path not null terminated");
  940. X
  941. X    for(s = path, state = 0; *s; s++)
  942. X    {
  943. X    if(*s <= ' ' || *s >= '~') return("Path contains illegal chars");
  944. X
  945. X    switch(*s)
  946. X    {
  947. X        case '.': if(!state) return("Path can't begin with '.'");
  948. X              break;
  949. X
  950. X        case '/': if(!state) return("Path can't contain '//'");
  951. X              state = 0;
  952. X              break;
  953. X
  954. X        default : state = 1;
  955. X              break;
  956. X    }
  957. X    }
  958. X
  959. X    return(NULLP);
  960. X}
  961. X
  962. X/*****************************************************************************
  963. X* Put the directory name of path into dbuf.
  964. X*****************************************************************************/
  965. X
  966. char *get_dir_name(path,dbuf)
  967. X    char *path, *dbuf;
  968. X{
  969. X    char *p1,*p2,*p3;
  970. X
  971. X    for(p1 = path, p2 = p3 = dbuf; *p1; p1++, p3++)
  972. X    {
  973. X    if((*p3 = *p1) == '/') p2 = p3;
  974. X    }
  975. X
  976. X    if(dbuf == p2) { dbuf[0] = '.'; dbuf[1] = 0; }
  977. X          else { *p2 = 0;             }
  978. X
  979. X    return(dbuf);
  980. X}
  981. X
  982. X/*****************************************************************************
  983. X* Reads directory and write directory listing file.
  984. X*****************************************************************************/
  985. X
  986. static build_dir_file(fp)
  987. X    FILE *fp;
  988. X{
  989. X    int nlen, skip, rem;
  990. X    DIR *dir_f;
  991. X    struct dirent *dp;
  992. X    struct stat    sb;
  993. X    register char  *s;
  994. X    RDIRENT rdb;
  995. X    static char marker[] = "******************";
  996. X
  997. X    if(!(dir_f = opendir(".")))    /* assume I have cd to path already */
  998. X    { fprintf(stderr,"Can't open dir during initialization\n"); exit(1); }
  999. X
  1000. X    for(rem = UBUF_SPACE; dp = readdir(dir_f); )
  1001. X    {
  1002. X    if (dp->d_ino == 0) continue;
  1003. X    s = dp->d_name;
  1004. X                        /* hide dot files */
  1005. X    if((s[0] == '.') && ((s[1] !=  0 ) &&
  1006. X                 (s[1] != '.' || s[2] != 0))) continue;
  1007. X
  1008. X    if(stat(dp->d_name,&sb)) continue;
  1009. X
  1010. X    nlen = strlen(s)+1;
  1011. X
  1012. X    if(rem < RDHSIZE + nlen)
  1013. X    {
  1014. X        rdb.type = RDTYPE_SKIP;
  1015. X        if(rem <= RDHSIZE) { fwrite(marker,1,rem    ,fp); }
  1016. X              else { fwrite(marker,1,RDHSIZE,fp);
  1017. X                 fwrite(s, 1,rem-RDHSIZE,fp); }
  1018. X        rem = UBUF_SPACE;
  1019. X    }
  1020. X
  1021. X    rdb.type = ((S_IFDIR & sb.st_mode)) ? RDTYPE_DIR : RDTYPE_FILE;
  1022. X    rdb.size = htonl(sb.st_size);
  1023. X    rdb.time = htonl(sb.st_mtime);
  1024. X
  1025. X    fwrite(&rdb,1,RDHSIZE,fp);
  1026. X    fwrite(s,1,nlen,fp);
  1027. X    rem -= (nlen + RDHSIZE);
  1028. X
  1029. X    if((skip = (nlen + RDHSIZE) & 0x3))
  1030. X        { fwrite(&rdb,1,4-skip,fp); rem -= (4-skip); }
  1031. X
  1032. X    if(!rem) rem = UBUF_SPACE;
  1033. X    }
  1034. X
  1035. X    rdb.type = RDTYPE_END;
  1036. X    fwrite(&rdb,1,RDHSIZE,fp);
  1037. X
  1038. X    fflush(fp);
  1039. X    closedir(dir_f);
  1040. X}
  1041. X
  1042. X/***************************************************************************/
  1043. X
  1044. char *server_get_dir(path,fp)    /* assume path is validated */
  1045. X    char *path;            /* returned file may not point at BOF */
  1046. X    FILE **fp;
  1047. X{
  1048. X    struct stat sd, sf;
  1049. X    char   list_p[NBSIZE];
  1050. X
  1051. X    if(!*path) path = ".";
  1052. X    if(stat(path,&sd)) return("Can't find directory");
  1053. X    if(!(S_IFDIR & sd.st_mode)) return("Not a directory");
  1054. X
  1055. X    sprintf(list_p,"%s/.FSP_CONTENT",path);
  1056. X
  1057. X    if(!stat(list_p,&sf) && (sf.st_mtime >= sd.st_mtime))
  1058. X    {
  1059. X    *fp = fopen(list_p,"r");
  1060. X    if(!*fp) return("Can't read directory listing");
  1061. X    return((char *)0);
  1062. X    }
  1063. X
  1064. X    if(!(*fp = fopen(list_p,"w+"))) return("Can't create directory listing");
  1065. X    if(chdir(path)) return("Can't cd to directory");
  1066. X    build_dir_file(*fp);
  1067. X    if(chdir(home_dir) == -1) { perror("chdir2"); exit(1); }
  1068. X    return(NULLP);
  1069. X}
  1070. X
  1071. X/**********************************************************************/
  1072. X
  1073. char *server_del_file(path,inet_num)        /* assume path is validated */
  1074. X    char *path;
  1075. X    unsigned long inet_num;
  1076. X{
  1077. X    struct stat sb;
  1078. X    char   dir_p[NBSIZE], no_del_p[NBSIZE], owner_p[NBSIZE];
  1079. X
  1080. X    if(stat(path,&sb)) return("unlink: file not accessible");
  1081. X    if(!(S_IFREG & sb.st_mode)) return("unlink: not an ordinary file");
  1082. X
  1083. X    get_dir_name(path,dir_p);
  1084. X    sprintf(owner_p ,"%s/.OWN.%08X"  ,dir_p,inet_num);
  1085. X    sprintf(no_del_p,"%s/.FSP_NO_DEL",dir_p         );
  1086. X
  1087. X    if(!fexist(owner_p) && fexist(no_del_p))
  1088. X            return("no permission for removing this file");
  1089. X
  1090. X    if(unlink(path) == -1) return("unlink: cannot unlink");
  1091. X
  1092. X    return(NULLP);
  1093. X}
  1094. X
  1095. X/**********************************************************************/
  1096. X
  1097. char *server_del_dir(path,inet_num)        /* assume path is validated */
  1098. X    char *path;
  1099. X    unsigned long inet_num;
  1100. X{
  1101. X    struct stat sb;
  1102. X    char   dir_p[NBSIZE], no_del_p[NBSIZE], no_add_p[NBSIZE], owner_p[NBSIZE];
  1103. X    int    has_no_del_p, has_no_add_p;
  1104. X
  1105. X    if(stat(path,&sb)) return("rmdir: directory not accessible");
  1106. X    if(!(S_IFDIR & sb.st_mode)) return("rmdir: not an ordinary directory");
  1107. X
  1108. X    get_dir_name(path,dir_p);
  1109. X    sprintf( owner_p,"%s/.OWN.%08X"  ,dir_p,inet_num);
  1110. X    sprintf(no_del_p,"%s/.FSP_NO_DEL",dir_p         );
  1111. X
  1112. X    if(!fexist(owner_p) && fexist(no_del_p))
  1113. X            return("no permission for removing this directory");
  1114. X
  1115. X    sprintf( owner_p,"%s/.OWN.%08X"   ,path,inet_num);
  1116. X    sprintf(   dir_p,"%s/.FSP_CONTENT",path         );
  1117. X    sprintf(no_del_p,"%s/.FSP_NO_DEL" ,path                );
  1118. X    sprintf(no_add_p,"%s/.FSP_NO_ADD" ,path                );
  1119. X
  1120. X    if(!fexist(owner_p)) return("no permission for removing this directory");
  1121. X
  1122. X    unlink(owner_p); unlink(  dir_p);
  1123. X    has_no_del_p = !unlink(no_del_p);
  1124. X    has_no_add_p = !unlink(no_add_p);
  1125. X
  1126. X    if(rmdir(path) != 0)
  1127. X    {
  1128. X    if(has_no_del_p) touch(no_del_p);
  1129. X    if(has_no_add_p) touch(no_add_p);
  1130. X    if(     owner_p) touch( owner_p);
  1131. X    return("rmdir: cannot unlink");
  1132. X    }
  1133. X
  1134. X    return(NULLP);
  1135. X}
  1136. X
  1137. X/**********************************************************************/
  1138. X
  1139. char *server_make_dir(path,inet_num)        /* assume path is validated */
  1140. X    char *path;
  1141. X    unsigned long inet_num;
  1142. X{
  1143. X    char   dir_p[NBSIZE], no_del_p[NBSIZE], no_add_p[NBSIZE], owner_p[NBSIZE];
  1144. X
  1145. X    get_dir_name(path,dir_p);
  1146. X    sprintf( owner_p,"%s/.OWN.%08X"  ,dir_p,inet_num);
  1147. X    sprintf(no_add_p,"%s/.FSP_NO_ADD",dir_p         );
  1148. X
  1149. X    if(!fexist(owner_p) && fexist(no_add_p))
  1150. X            return("no permission for directory creation");
  1151. X
  1152. X    sprintf( owner_p,"%s/.OWN.%08X"   ,path,inet_num);
  1153. X    sprintf(   dir_p,"%s/.FSP_CONTENT",path         );
  1154. X    sprintf(no_del_p,"%s/.FSP_NO_DEL" ,path         );
  1155. X    sprintf(no_add_p,"%s/.FSP_NO_ADD" ,path         );
  1156. X
  1157. X    if(mkdir(path,0777) != 0) return("Can't create directory");
  1158. X
  1159. X    touch(no_del_p);
  1160. X    touch(no_add_p);
  1161. X    touch( owner_p);
  1162. X    return(NULLP);
  1163. X}
  1164. X
  1165. X/**********************************************************************/
  1166. X
  1167. char *server_get_file(path,fp)        /* assume path is validated */
  1168. X    char *path;
  1169. X    FILE **fp;
  1170. X{
  1171. X    struct stat sb;
  1172. X
  1173. X    if(stat(path,&sb)) return("Can't find file");
  1174. X    if(!(S_IFREG & sb.st_mode)) return("Not a file");
  1175. X    if(!(*fp = fopen(path,"r"))) return("Can't open file");
  1176. X    return(NULLP);
  1177. X}
  1178. X
  1179. X/**********************************************************************/
  1180. X
  1181. char *server_get_pro(s,inet_num)    /* s is both I and O */
  1182. X    char *s;
  1183. X    unsigned long inet_num;
  1184. X{
  1185. X    struct stat sb;
  1186. X    char   buf[NBSIZE];
  1187. X    char  *owner_s, *del_s, *add_s;
  1188. X
  1189. X    if(stat(s,&sb)) return("getpro: directory not accessible");
  1190. X    if(!(S_IFDIR & sb.st_mode)) return("getpro: not an ordinary directory");
  1191. X
  1192. X    sprintf(buf,"%s/.OWN.%08X",s,inet_num);
  1193. X    owner_s = (fexist(buf)) ? "your" : "some other";
  1194. X    sprintf(buf,"%s/.FSP_NO_DEL" ,s); del_s = (fexist(buf)) ? "NO" : "YES";
  1195. X    sprintf(buf,"%s/.FSP_NO_ADD" ,s); add_s = (fexist(buf)) ? "NO" : "YES";
  1196. X
  1197. X    sprintf(s,"(owner: %s machine)(delete: %s)(create: %s)",
  1198. X                        owner_s, del_s, add_s);
  1199. X    return(NULLP);
  1200. X}
  1201. X
  1202. X/**********************************************************************/
  1203. X
  1204. char *server_set_pro(path,key,inet_num)
  1205. X    char *path, *key;
  1206. X    unsigned long inet_num;
  1207. X{
  1208. X    struct stat sb;
  1209. X    char   buf[NBSIZE];
  1210. X
  1211. X    if(stat(path,&sb)) return("getpro: directory not accessible");
  1212. X    if(!(S_IFDIR & sb.st_mode)) return("getpro: not an ordinary directory");
  1213. X
  1214. X    sprintf(buf,"%s/.OWN.%08X",path,inet_num);
  1215. X    if(!fexist(buf)) return("no permission for changing the protection-mode");
  1216. X
  1217. X    switch(key[1])
  1218. X    {
  1219. X    case 'c': sprintf(buf,"%s/.FSP_NO_ADD",path); break;
  1220. X    case 'd': sprintf(buf,"%s/.FSP_NO_DEL",path); break;
  1221. X    default : return("bad flag");
  1222. X    }
  1223. X
  1224. X    switch(key[0])
  1225. X    {
  1226. X    case '-': touch(buf);  break;
  1227. X    case '+': unlink(buf); break;
  1228. X    default : return("bad flag");
  1229. X    }
  1230. X
  1231. X    return(NULLP);
  1232. X}
  1233. X
  1234. X/**********************************************************************
  1235. X*  These two are used for file uploading.
  1236. X**********************************************************************/
  1237. X
  1238. char *server_up_load(data,len,pos,inet_num)
  1239. X    char *data;
  1240. X    unsigned len;
  1241. X    unsigned long pos, inet_num;
  1242. X{
  1243. X    FILE *fp;
  1244. X    char  tname[NBSIZE];
  1245. X
  1246. X    sprintf(tname,".TMP.%08X",inet_num);
  1247. X
  1248. X    if(pos) {             fp = fopen(tname,"a"); }
  1249. X       else { unlink(tname); fp = fopen(tname,"w"); }
  1250. X
  1251. X    if(!fp) return("Cannot open temporary file");
  1252. X
  1253. X    fwrite(data, 1, len, fp);
  1254. X    fclose(fp);
  1255. X
  1256. X    return(NULLP);
  1257. X}
  1258. X
  1259. char *server_install(path,inet_num)
  1260. X    char *path;
  1261. X    unsigned long inet_num;
  1262. X{
  1263. X    FILE *ft, *fp;
  1264. X    char   tname[NBSIZE], no_add_p[NBSIZE], owner_p[NBSIZE], buf[512];
  1265. X    int bytes;
  1266. X
  1267. X    get_dir_name(path,tname);
  1268. X    sprintf( owner_p,"%s/.OWN.%08X"  ,tname,inet_num);
  1269. X    sprintf(no_add_p,"%s/.FSP_NO_ADD",tname         );
  1270. X    sprintf(tname,".TMP.%08X"        ,      inet_num);
  1271. X
  1272. X    if(!fexist(owner_p) && fexist(no_add_p))
  1273. X    {
  1274. X    unlink(tname);
  1275. X    return("no permission for writting to that file");
  1276. X    }
  1277. X
  1278. X    unlink(path);
  1279. X    if(link(tname,path) == 0) { unlink(tname); return(NULLP); }
  1280. X
  1281. X    if(!(ft = fopen(tname,"r"))) { unlink(tname);
  1282. X                   return("Can't open temporary file"); }
  1283. X
  1284. X    if(!(fp = fopen(path ,"w"))) { unlink(tname); fclose(ft);
  1285. X                   return("Can't open file for output"); }
  1286. X
  1287. X    while(bytes = fread(buf,1,sizeof(buf),ft)) fwrite(buf,1,bytes,fp);
  1288. X
  1289. X    fclose(ft); fclose(fp); unlink(tname); return(NULLP);
  1290. X}
  1291. X
  1292. X/**********************************************************************/
  1293. X
  1294. init_home_dir()
  1295. X{
  1296. X    if(*home_dir != '/') { fprintf(stderr,"[%s] does not start with a /\n");
  1297. X               exit(1); }
  1298. X
  1299. X    if(chdir(home_dir) == -1) { perror("chdir"); exit(1); }
  1300. X
  1301. X    if(dbug) { fprintf(stderr,"home on %s\n",home_dir); fflush(stderr); }
  1302. X}
  1303. X
  1304. X/***************************************************************************/
  1305. END_OF_FILE
  1306. if test 11591 -ne `wc -c <'server_file.c'`; then
  1307.     echo shar: \"'server_file.c'\" unpacked with wrong size!
  1308. fi
  1309. # end of 'server_file.c'
  1310. fi
  1311. echo shar: End of archive 3 \(of 3\).
  1312. cp /dev/null ark3isdone
  1313. MISSING=""
  1314. for I in 1 2 3 ; do
  1315.     if test ! -f ark${I}isdone ; then
  1316.     MISSING="${MISSING} ${I}"
  1317.     fi
  1318. done
  1319. if test "${MISSING}" = "" ; then
  1320.     echo You have unpacked all 3 archives.
  1321.     rm -f ark[1-9]isdone
  1322. else
  1323.     echo You still need to unpack the following archives:
  1324.     echo "        " ${MISSING}
  1325. fi
  1326. ##  End of shell archive.
  1327. exit 0
  1328.